package cn.egame.extraction;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;

import cn.egame.common.efs.IFileSystem;
import cn.egame.common.efs.SFileSystemClient;
import cn.egame.common.exception.ExceptionCommonBase;
import cn.egame.common.util.Utils;
import cn.egame.common.web.ExceptionWeb;
import cn.egame.common.web.WebUtils;
import cn.egame.extraction.pojo.EfsInfo;
import cn.egame.extraction.util.ConstVar_EFS;
import cn.egame.extraction.util.EnumType_EFS.EfsInfoFromType;
import cn.egame.extraction.util.EnumType_EFS.InputErrorFileAppendType;
import cn.egame.interfaces.fl.FileUsedType;
import cn.egame.interfaces.fl.FileUtils;


public class FileSynchronize {
	static{
		Utils.initLog4j();
	}
	private static Logger logger = Logger.getLogger(FileSynchronize.class);
	private static Logger successSyncIdLog = Logger.getLogger("sucessSyncId");
	private static Logger errorSyncIdLog = Logger.getLogger("errorSyncId");
	
	private long readMaxId;
	private long writeMaxId;
	private List<EfsInfo> efsInfoList = new ArrayList<EfsInfo>();
	private String dayStr;//2013-11-04
	
	//写入拉取的文件失败错误文件的模式(w:覆盖, a:向后添加)
	private InputErrorFileAppendType fetchErrorEfsInfosMode = InputErrorFileAppendType.append;
	//写入拉取的文件不存在错误文件的模式(w:覆盖, a:向后添加)
	private InputErrorFileAppendType connectionErrorEfsMode = InputErrorFileAppendType.append;
	
	public FileSynchronize() throws ExceptionCommonBase{
		File file = new File(ConstVar_EFS.MAX_ID_FILE_PATH);
		File dayFile = new File(ConstVar_EFS.DAY_FILE_PATH);
		if(!file.exists()
				|| !dayFile.exists()){
			throw new ExceptionCommonBase(-1, "存储最大id的文件或存储日期的文件不存在");
		}
		
		BufferedReader br = null;
		BufferedReader br2 = null;
		try {
			br = new BufferedReader(new InputStreamReader(
					new FileInputStream(file),"utf-8"));
			br2 = new BufferedReader(new InputStreamReader(
					new FileInputStream(dayFile),"utf-8"));
			readMaxId = new Long(br.readLine());
			dayStr = br2.readLine();
		} catch (Exception e) {
			logger.error(e);
			throw new ExceptionCommonBase(-1, "从文件中读取id失败");
		} finally{
			if(br!=null){
				try {
					br.close();
				} catch (IOException e) {
					logger.error(e);
					throw ExceptionCommonBase.throwExceptionCommonBase(e);
				}
			}
			if(br2!=null){
				try {
					br2.close();
				} catch (IOException e) {
					logger.error(e);
					throw ExceptionCommonBase.throwExceptionCommonBase(e);
				}
			}
		}
		if(readMaxId==0L){
			throw new ExceptionCommonBase(-1, "文件中id为0");
		}
		if(dayStr==null || !dayStr.matches("^\\d+-\\d+-\\d+$")){
			throw new ExceptionCommonBase(-1, "文件中日期不存在或日期格式不符合需求");
		}
		//从拉取失败的文件中填充重新需要拉取的id
		fillEfsInfoListFromErrorFile();
		//路径是由日期生成的文件解析
		if(ConstVar_EFS.DAY_FILE_PATH!=null){
			String[] monthFileTypes = ConstVar_EFS.DAY_FILE_TYPE.split(",");
			for(String fileType : monthFileTypes){
				String url2 = ConstVar_EFS.MAX_ID_URL+
						contactUrl("efs_id="+readMaxId,"efs_type="+fileType,"num=0","day="+dayStr);
				logger.info(url2);
				parseMaxIdUrlInfo(url2);
			}
		}
		//路径是由efs生成的文件解析
		String url = ConstVar_EFS.MAX_ID_URL+
				contactUrl("efs_id="+readMaxId,"efs_type="+ConstVar_EFS.EFS_TYPE,"num="+ConstVar_EFS.NUM,"end_id="+ConstVar_EFS.END_ID);
		logger.info(url);
		parseMaxIdUrlInfo(url);
		if(writeMaxId<readMaxId){
			throw new ExceptionCommonBase(-1, "返回的maxId小于读取的maxId");
		}
				
	}

	/**
	 * @Description: 根据配置文件中的key=refetch_error_ids_file_paths填充需要重新拉取的文件
	 * @Author yuchao
	 * @Create Date  2013-10-29
	 * @Modified by none
	 * @Modified Date
	 */
	private void fillEfsInfoListFromErrorFile()
			throws ExceptionCommonBase {
		List<EfsInfo> efsInfosIn = new ArrayList<EfsInfo>();
		String filePaths = ConstVar_EFS.REFETCH_ERROR_IDS_FILE_PATHS.trim(); 
		String[] refetchFilePaths = filePaths.split(",");
		for(String filePath : refetchFilePaths){
			List<EfsInfo> efsInfos = getEfsInfosFromFile(filePath);
			if(ConstVar_EFS.FETCH_ERROR_IDS_FILE_PATH.equals(filePath)){
				fetchErrorEfsInfosMode = InputErrorFileAppendType.rewrite;
			}else if(ConstVar_EFS.CONNECT_ERROR_IDS_FILE_PATH.equals(filePath)){
				connectionErrorEfsMode = InputErrorFileAppendType.rewrite;
			}
			efsInfosIn = Utils.collectionsAdd(efsInfosIn, efsInfos);
		}
		for(EfsInfo info : efsInfosIn){
			efsInfoList.add(info);
		}
	}
	
	/**
	 * @Description: 同步文件
	 * @Author yuchao
	 * @Create Date  2013-9-30
	 * @Modified by none
	 * @Modified Date
	 */
	private void syncFile() throws ExceptionCommonBase {
		String localfilePath = null;
		for(EfsInfo efsInfo : efsInfoList){
//			String filePath = null;
			if(efsInfo.getEfs_type().matches("^\\d+$")){
				int efsTypeNum = Utils.toInt(efsInfo.getEfs_type(), 0);
				try {
					List<String> filePathList = new ArrayList<String>();
					localfilePath = FileUtils.getFilePath(FileUsedType.lookup(efsTypeNum), 
							efsInfo.getEfs_id(), efsInfo.getFile_name());
					filePathList.add(localfilePath);
					//以下三种图片文件类型需要拉取压缩的多份
					if (efsTypeNum == FileUsedType.GAME_PHOTO) {
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.GAME_PHOTO_BIG), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.GAME_PHOTO_MID), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.GAME_PHOTO_SMALL), 
                                efsInfo.getEfs_id(), efsInfo.getFile_name()));
					} else if (efsTypeNum == FileUsedType.HEAD_PHOTO) {
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.HEAD_SML), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.HEAD_MID), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.HEAD_BIG), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
					} else if (efsTypeNum == FileUsedType.ALBUM_PHOTO) {
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.ALBUM_PHOTO_SML), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.ALBUM_PHOTO_MID), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.ALBUM_PHOTO_BIG), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
					}  else if (efsTypeNum == FileUsedType.GAME_VIEW) {
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.GAME_VIEW_BIG), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.GAME_VIEW_MID), 
								efsInfo.getEfs_id(), efsInfo.getFile_name()));
						filePathList.add(FileUtils.getFilePath(FileUsedType.lookup(FileUsedType.GAME_VIEW_SMALL), 
                                efsInfo.getEfs_id(), efsInfo.getFile_name()));
					}
					
					logger.info("准备拉取id为"+efsInfo.getEfs_id()+"的文件");
					//先判断该id对应的文件是否存在
					boolean exists = isFilesExists(filePathList);
					if (exists) {
						logger.info("id为" + efsInfo.getEfs_id() + "的文件已存在");
						fetchOkAndWriteBack(efsInfo);
						// 防止存储id的文件中id过小,走不到下面的storeIdToFile方法,
						// 存储id的文件就一直不会更新,所以这边需要调用storeIdToFile方法
						// 只有从url中拉取的文件id才需要写入max_id文件
						if (efsInfo.getType() == EfsInfoFromType.fromUrl) {
							storeIdToFile(efsInfo.getEfs_id() + 1,
									ConstVar_EFS.MAX_ID_FILE_PATH);
						}
						continue;
					}
					
					for (String filePath : filePathList) {
						try {
							int i = catchFile(1, efsInfo, filePath);
							localfilePath = filePath;
							File file = new File(ConstVar_EFS.UPLOAD_ADDRESS+filePath);//TODO
							long length = getInputStreamLengthFromUrl(ConstVar_EFS.DNS_HOST + filePath);
							if (i > ConstVar_EFS.REPEAT_READ_NUM || !file.exists()
									|| file.length()!=length) {
								logger.error("(i > ConsVar_EFS.REPEAT_READ_NUM) --->"+(i > ConstVar_EFS.REPEAT_READ_NUM));
								logger.error("(!file.exists()) --->"+(!file.exists()));
								logger.error("(file.length()!=length) --->"+(file.length()!=length));
								throw new ExceptionCommonBase(-1, "文件拉取失败");	
							}
						} catch(ExceptionWeb ew){
							logger.error(ew);
							errorSyncIdLog.error("id为"+efsInfo.getEfs_id()+"类型为:"+efsInfo.getEfs_type()+"的文件拉取失败,异常信息为:"+ew.getMessage()+" 对应的url为:"+ConstVar_EFS.DNS_HOST+filePath);
							writeBackToErrorFilePath(ConstVar_EFS.CONNECT_ERROR_IDS_FILE_PATH,
									connectionErrorEfsMode, efsInfo, 1);
						} catch (Exception e) {
							logger.error(e);
							errorSyncIdLog.error("id为"+efsInfo.getEfs_id()+"类型为:"+efsInfo.getEfs_type()+"的文件拉取失败, 对应的url为:"+ConstVar_EFS.DNS_HOST+filePath);
							writeBackToErrorFilePath(ConstVar_EFS.FETCH_ERROR_IDS_FILE_PATH,
									fetchErrorEfsInfosMode , efsInfo, 1);
						}
					}
					if(efsInfo.getType() == EfsInfoFromType.fromUrl){
						storeIdToFile(efsInfo.getEfs_id()+1, ConstVar_EFS.MAX_ID_FILE_PATH);
					}
					exists = isFilesExists(filePathList);
					if(exists){
						fetchOkAndWriteBack(efsInfo);
					}
				} catch (Exception e) {
					errorSyncIdLog.error("id为"+efsInfo.getEfs_id()+"的文件拉取失败, 对应的url为:"+ConstVar_EFS.DNS_HOST+localfilePath);
					writeBackToErrorFilePath(ConstVar_EFS.FETCH_ERROR_IDS_FILE_PATH,
							fetchErrorEfsInfosMode, efsInfo, 1);
				}
			}else{
				try {
					logger.info("准备拉取类型为"+efsInfo.getEfs_type()+",路径为"+ConstVar_EFS.DNS_HOST+efsInfo.getFile_name()+"的文件");
					//先判断该id对应的文件是否存在
					List<String> filePathList = new ArrayList<String>();
					filePathList.add(efsInfo.getFile_name());
					boolean exists = isFilesExists(filePathList);
					if (exists) {
						logger.info("类型为" + efsInfo.getEfs_type() +",路径为"+ConstVar_EFS.UPLOAD_ADDRESS+efsInfo.getFile_name()+ "的文件已存在");
						continue;
					}
					int i = catchFile(1, efsInfo, efsInfo.getFile_name());
					File file = new File(ConstVar_EFS.UPLOAD_ADDRESS+efsInfo.getFile_name());
					long length = getInputStreamLengthFromUrl(ConstVar_EFS.DNS_HOST + efsInfo.getFile_name());
					if (i > ConstVar_EFS.REPEAT_READ_NUM || !file.exists()
							|| file.length()!=length) {
						logger.error("(i > ConsVar_EFS.REPEAT_READ_NUM) --->"+(i > ConstVar_EFS.REPEAT_READ_NUM));
						logger.error("(!file.exists()) --->"+(!file.exists()));
						logger.error("(file.length()!=length) --->"+(file.length()!=length));
						throw new ExceptionCommonBase(-1, "文件拉取失败");	
					}
					exists = isFilesExists(filePathList);
					if(exists){
						fetchOkAndWriteBack(efsInfo);
					}
				} catch (ExceptionWeb ew) {
					errorSyncIdLog.error("类型为:"+ efsInfo.getEfs_type()+",路径为"+ConstVar_EFS.DNS_HOST+efsInfo.getFile_name()
							+ "的文件拉取失败,异常信息为:" + ew.getMessage());
					writeBackToErrorFilePath(ConstVar_EFS.CONNECT_ERROR_IDS_FILE_PATH,connectionErrorEfsMode, efsInfo, 1);
				} catch (Exception e) {
					errorSyncIdLog.error("类型为:"+ efsInfo.getEfs_type()+",路径为"+ConstVar_EFS.DNS_HOST+efsInfo.getFile_name()+"的文件拉取失败");
					writeBackToErrorFilePath(ConstVar_EFS.FETCH_ERROR_IDS_FILE_PATH, fetchErrorEfsInfosMode, efsInfo, 1);
				}
			}
		}
		storeIdToFile(writeMaxId, ConstVar_EFS.MAX_ID_FILE_PATH);
		storeDayToFile();
	}

	/**
	 * @Description: 根据日期生成文件路径的日期递增重新写回文件
	 * @Author yuchao
	 * @Create Date  2013-11-7
	 * @Modified by none
	 * @Modified Date
	 */
	private void storeDayToFile() {
		try {
			String dateStrBack = "";
			String dateStrNow = Utils.toDateString(new Date(), "yyyy-MM-dd");
			if(dateStrNow.equals(dayStr)){
				dateStrBack = dateStrNow;
			}else{
				Long dateLong = Utils.toDateLong(dayStr, "yyyy-MM-dd");
				Calendar calendar = new GregorianCalendar();
				calendar.setTime(new Date(dateLong));
				calendar.add(Calendar.DAY_OF_MONTH, 1);
				dateStrBack = Utils.toDateString(calendar.getTime(), "yyyy-MM-dd");
			}
			
			
			PrintWriter pw = null;
			try {
				pw = new PrintWriter(new OutputStreamWriter(
						new FileOutputStream(ConstVar_EFS.DAY_FILE_PATH),"utf-8"), false);
					pw.println(dateStrBack);
			} catch (FileNotFoundException e) {
				logger.error(e);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} finally{
				if(pw!=null){
					pw.close();
				}
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
	}

	private boolean isFilesExists(List<String> filePathList){
		boolean exists = true;
		for(String filePath : filePathList){
			String localFilePath = ConstVar_EFS.UPLOAD_ADDRESS+filePath;
			File file = new File(localFilePath);
			long length;
			try {
				length = getInputStreamLengthFromUrl(ConstVar_EFS.DNS_HOST + filePath);
			} catch (IOException e) {
				length = -1;
			}
			if(!file.exists() ||
					file.length()!=length){
				exists = false;
			}
		}
		return exists;
	}

	/**
	 * @Description: 写回错误文件的list需要删除拉取成功对应的efsInfo,并重新写回文件
	 * @Author yuchao
	 * @Create Date  2013-10-29
	 * @Modified by none
	 * @Modified Date
	 */
	private void fetchOkAndWriteBack(EfsInfo efsInfo)
			throws ExceptionCommonBase {
		if(InputErrorFileAppendType.rewrite.equals(fetchErrorEfsInfosMode)){
			writeBackToErrorFilePath(ConstVar_EFS.FETCH_ERROR_IDS_FILE_PATH,
					fetchErrorEfsInfosMode, efsInfo, -1);
		}
		if(InputErrorFileAppendType.rewrite.equals(connectionErrorEfsMode)){
			writeBackToErrorFilePath(ConstVar_EFS.CONNECT_ERROR_IDS_FILE_PATH,
					connectionErrorEfsMode, efsInfo, -1);
		}
	}

	/**
	 * @Description: 将拉取错误的文件信息写回文件.可以重新拉取
	 * @Author yuchao
	 * @Create Date  2013-10-29
	 * @Modified by none
	 * @Modified Date
	 */
	private void writeBackToErrorFilePath(String path, InputErrorFileAppendType mode,
			EfsInfo efsInfo, int sth) throws ExceptionCommonBase {
		List<EfsInfo> list = new ArrayList<EfsInfo>();
		boolean append = true;
		if(InputErrorFileAppendType.rewrite.equals(mode)){
			list = initInputEfsInfos(path);
			if(efsInfo!=null){
				if(sth==-1){
					list.remove(efsInfo);
				}else if(sth==1){
					list.add(efsInfo);
				}
			}
			Set<EfsInfo> fetchSet = new HashSet<EfsInfo>(list);
			list.clear();
			list.addAll(fetchSet);
			Collections.sort(list);
			append = false;
			
		}
		else if(InputErrorFileAppendType.append.equals(mode)){
			list.add(efsInfo);
			append = true;
		}
		storeEfsInfoListToFile(list, path, append);
	}
	
	
	
	/**
	 * @throws ExceptionWeb 
	 * @Description: 抓取文件
	 * @Author yuchao
	 * @Create Date  2013-9-30
	 * @Modified by none
	 * @Modified Date
	 */
	private int catchFile(int catchTimes, EfsInfo efsInfo, String filePath) throws Exception{
		if(catchTimes>ConstVar_EFS.REPEAT_READ_NUM)
			return catchTimes;
		InputStream inputStream = null;
		String writePath = ConstVar_EFS.UPLOAD_WRITE_ADDRESS + filePath;
		File file = null;
		try {
			logger.info("开始第"+(catchTimes)+"次拉取id为"+efsInfo.getEfs_id()
					+"类型为"+efsInfo.getEfs_type()+",路径为"+ConstVar_EFS.DNS_HOST+filePath+"的文件");
			
			inputStream = getInputStreamFromUrl(ConstVar_EFS.DNS_HOST + filePath);
			long size = getInputStreamLengthFromUrl(ConstVar_EFS.DNS_HOST + filePath);
			IFileSystem fileSystem = SFileSystemClient.getInstance("mobile");
            logger.info("writePath:" + writePath);
            file = new File(writePath);
            fileSystem.mkdirs(writePath);
            int fileSize = fileSystem.uploadFile(writePath, inputStream);
            if(fileSize!=size){
            	throw new Exception("文件拉取失败");
            }
			successSyncIdLog.info("id为"+efsInfo.getEfs_id()+"类型为:"+efsInfo.getEfs_type()+"的文件拉取成功, 对应的url为:"+ConstVar_EFS.DNS_HOST+filePath);
		} catch(ExceptionWeb ew){
			if(file!=null){
				file.delete();
			}
			throw ew;
		} catch (Exception e) {
			if(file!=null){
				file.delete();
			}
			return catchFile(++catchTimes, efsInfo, filePath);
		} finally{
			if(inputStream!=null){
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return catchTimes;
	}
	
	public static InputStream getInputStreamFromUrl(String url) throws IOException{
        HttpClient httpClient = new DefaultHttpClient();
        
        HttpGet httpGet = new HttpGet(getEncodeUrl(url));
        HttpContext localContext = new BasicHttpContext();
		HttpResponse response = httpClient.execute(httpGet, localContext);
		int statusCode = response.getStatusLine().getStatusCode();
		if (statusCode != HttpStatus.SC_OK) {
			throw new ExceptionWeb(url + "对应的文件不存在");
		}
		return response.getEntity().getContent();
    }
	
	public static long getInputStreamLengthFromUrl(String url) throws IOException{
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(getEncodeUrl(url));
        HttpContext localContext = new BasicHttpContext();
		HttpResponse response = httpClient.execute(httpGet, localContext);
		int statusCode = response.getStatusLine().getStatusCode();
		if (statusCode != HttpStatus.SC_OK) {
			throw new ExceptionWeb(url + "对应的文件不存在");
		}
		return response.getEntity().getContentLength();
    }
	
	private void parseMaxIdUrlInfo(String url) throws ExceptionCommonBase{
		try {
			String urlContent = WebUtils.http(url, "GET", "utf-8", null, null, null);
			ObjectMapper jsonMapper = new ObjectMapper();
            JsonNode jn = jsonMapper.readTree(urlContent);
            if(jn.get("ext")!=null && jn.get("ext").get("list_efs")!=null
                    && jn.get("ext").get("max_id")!=null){
                Iterator<JsonNode> it = jn.get("ext").get("list_efs").iterator();
                while(it.hasNext()){
                    JsonNode jn2 = (JsonNode) it.next();
                    EfsInfo efsInfo = new EfsInfo();
                    efsInfo.setEfs_id(jn2.get("efs_id").getLongValue());
                    efsInfo.setEfs_type(jn2.get("efs_type").getTextValue());
//                    efsInfo.setEfs_type(jn2.get("efs_type").getLongValue()+"");
                    efsInfo.setFile_name(jn2.get("file_name").getTextValue());
                    efsInfo.setType(EfsInfoFromType.fromUrl);//从url中拉取的标示
                    efsInfoList.add(efsInfo);
                }
                writeMaxId = jn.get("ext").get("max_id").getLongValue();
            }else{
            	throw new ExceptionCommonBase(-1, "同步数据的接口访问出错...");
            }
		} catch (Exception e) {
			logger.error(e);
			throw ExceptionCommonBase.throwExceptionCommonBase(e);
		} 
	}
	
	private String contactUrl(String ...args){
		StringBuilder sb = new StringBuilder();
		for(int i=0; i<args.length; i++){
			if(i==0){
				sb.append("?").append(args[i]);
			}else{
				sb.append("&").append(args[i]);
			}
		}
		return sb.toString();
	}
	
	/**
	 * @Description: 将拉取的max_id写回max_id文件
	 * @Author yuchao
	 * @Create Date  2013-10-29
	 * @Modified by none
	 * @Modified Date
	 */
	private void storeIdToFile(Long id, String filePath) throws ExceptionCommonBase{
		try {
			Thread.sleep(200);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
			throw ExceptionCommonBase.throwExceptionCommonBase(e1);
		}
		if (id < readMaxId || id > writeMaxId) {
			throw new ExceptionCommonBase(-1, "写回文件的id不正确...");
		}
		PrintWriter pw = null;
		try {
			pw = new PrintWriter(new OutputStreamWriter(
					new FileOutputStream(filePath),"utf-8"), false);
				pw.println(id);
		} catch (FileNotFoundException e) {
			logger.error(e);
			throw ExceptionCommonBase.throwExceptionCommonBase(e);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} finally{
			if(pw!=null){
				pw.close();
			}
		}
	}
	
	/**
	 * @Description: 拉取错误的实体list写回文件 
	 * @Author yuchao
	 * @Create Date  2013-10-29
	 * @Modified by none
	 * @Modified Date
	 */
	private void storeEfsInfoListToFile(List<EfsInfo> efsList, String filePath, Boolean append) throws ExceptionCommonBase{
		try {
			Thread.sleep(200);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
			throw ExceptionCommonBase.throwExceptionCommonBase(e1);
		}
		PrintWriter pw = null;
		try {
			pw = new PrintWriter(new OutputStreamWriter(
					new FileOutputStream(filePath,append), "utf-8"));
				for(EfsInfo info : efsList){
					try {
						if(info.getEfs_type().matches("^(-1)?\\d+$")){
							int efsTypeNum = Utils.toInt(info.getEfs_type(), 0);
							pw.println(info.getEfs_id()+","+info.getEfs_type()+","+info.getFile_name()+","+
									ConstVar_EFS.DNS_HOST+FileUtils.getFilePath(FileUsedType.lookup(efsTypeNum), 
											info.getEfs_id(), info.getFile_name()));
						}else{
							//cms, activity
							pw.println(info.getEfs_id()+","+info.getEfs_type()+","+info.getFile_name()+","+
									ConstVar_EFS.DNS_HOST+info.getFile_name());
						}
						
					} catch (NoSuchAlgorithmException e) {
						e.printStackTrace();
						continue;
					}
				}
		} catch (FileNotFoundException e) {
			logger.error(e);
			throw ExceptionCommonBase.throwExceptionCommonBase(e);
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		} finally{
			if(pw!=null){
				pw.close();
			}
		}
	}
	
	/**
	 * @Description: 从需要重新拉取的记录文件中组装出List 
	 * @Author yuchao
	 * @Create Date  2013-10-29
	 * @Modified by none
	 * @Modified Date
	 */
	private List<EfsInfo> getEfsInfosFromFile(String filePath) throws ExceptionCommonBase{
		List<EfsInfo> efsInfos = new ArrayList<EfsInfo>();
		File file = new File(filePath);
		if(!file.exists()){
			return efsInfos;
		}
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(
					new FileInputStream(file),"utf-8"));
			String idStr = null;
			while((idStr=br.readLine())!=null){
				String[] strs = idStr.trim().split(",");
				if(strs.length==4 
						&& strs[0].matches("\\d+")){
					EfsInfo efsInfo = new EfsInfo(
							Long.parseLong(strs[0]), 
							strs[1],
							strs[2],Long.parseLong(strs[3]),EfsInfoFromType.fromFile);
					efsInfos.add(efsInfo);
				}
			}
		} catch (Exception e) {
			logger.error(e);
			throw ExceptionCommonBase.throwExceptionCommonBase(e);
		} finally{
			if(br!=null){
				try {
					br.close();
				} catch (IOException e) {
					logger.error(e);
					throw ExceptionCommonBase.throwExceptionCommonBase(e);
				}
			}
		}
		Set<EfsInfo> fetchSet = new HashSet<EfsInfo>(efsInfos);
		efsInfos.clear();
		efsInfos.addAll(fetchSet);
		Collections.sort(efsInfos);
		return efsInfos;
	}
	
	private List<EfsInfo> initInputEfsInfos(String filePath) throws ExceptionCommonBase{
		return getEfsInfosFromFile(filePath);
	}
	
	public static void main(String[] args) throws ExceptionCommonBase {
		long startTime = System.currentTimeMillis();
        FileSynchronize sync = new FileSynchronize();
        sync.syncFile();
        long endTime = System.currentTimeMillis();
        logger.info("===============程序一共耗时====================("+(endTime-startTime)+")毫秒");
		
//		List<EfsInfo> list = new ArrayList<EfsInfo>();
//		EfsInfo ei1 = new EfsInfo(0, "cms", "/day/01", EfsInfoFromType.fromFile);
//		EfsInfo ei4 = new EfsInfo(0, "cms", "/day/01", EfsInfoFromType.fromFile);
//		EfsInfo ei2 = new EfsInfo(0, "cms", "/day/02", EfsInfoFromType.fromFile);
//		EfsInfo ei3 = new EfsInfo(0, "cms", "/day/03", EfsInfoFromType.fromFile);
//		list.add(ei1);
//		list.add(ei2);
//		list.add(ei3);
//		list.add(ei4);
//		System.out.println(list.size());
//		Set<EfsInfo> fetchSet = new HashSet<EfsInfo>(list);
//		list.clear();
//		list.addAll(fetchSet);
//		Collections.sort(list);
//		System.out.println(list.size());
        
    }
	
	public static String getEncodeUrl(String url)
			throws UnsupportedEncodingException {
		if(url==null){
			return url;
		}
		int idx = url.lastIndexOf("/");
		if(idx==-1 || idx+1>=url.length()){
			return url;
		}
		String subUrl = url.substring(0,idx+1);
		String name = url.substring(idx+1);
		name = URLEncoder.encode(name, "utf-8");
		if (name != null) {
			name = name.replace("+", "%20");
		}
		return subUrl+name;
	}
	
	public static String getDecodeStr(String str) 
			throws UnsupportedEncodingException {
		return URLDecoder.decode(str, "utf-8");
	}
	
}



